/*
 * Copyright © OpenAtom Foundation.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package io.iec.edp.caf.msu.client.register;

import io.iec.edp.caf.commons.runtime.CafEnvironment;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.commons.utils.StringUtils;
import io.iec.edp.caf.msu.api.ServiceUnitAwareService;
import io.iec.edp.caf.msu.api.client.ServiceRegistry;
import io.iec.edp.caf.msu.api.client.ServiceUnitInfoRegistry;
import io.iec.edp.caf.msu.api.entity.MsuProperties;
import io.iec.edp.caf.msu.api.entity.ServiceUnitInfo;
import io.iec.edp.caf.msu.api.entity.ServiceUnitRegisterInfo;
import io.iec.edp.caf.msu.api.server.MsuServiceRegistry;
import io.iec.edp.caf.msu.common.domain.entity.GspAppServerEntity;
import io.iec.edp.caf.msu.common.domain.entity.GspSuEntity;
import io.iec.edp.caf.msu.common.domain.repository.AppServerRepository;
import io.iec.edp.caf.msu.common.domain.repository.SuRepository;
import io.iec.edp.caf.msu.common.utils.NetUtil;
import io.iec.edp.caf.tenancy.api.context.MultiTenantContextInfo;
import io.iec.edp.caf.tenancy.core.context.MultiTenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.core.env.Environment;

import javax.annotation.PreDestroy;
import javax.management.MalformedObjectNameException;
import java.util.List;

/**
 * 本地文件部署，采用GSPAppServerInstance和GSPSUInstance表实现服务注册、发现
 * @author wangyandong
 * @date 2021/09/10 13:31
 *
 */
@Slf4j
public class DbRegisterImpl implements ServiceRegistry {
    private ServiceUnitAwareService suAware;
    private AppServerRepository repo;
    private SuRepository suRepo;
    private ServiceUnitInfoRegistry msuServiceRegistry= SpringBeanUtils.getBean(ServiceUnitInfoRegistry.class);
    private MsuProperties configuration;

    public DbRegisterImpl(ServiceUnitAwareService suAware, AppServerRepository repo, SuRepository suRepo,MsuProperties configuration) {
        this.suAware = suAware;
        this.repo = repo;
        this.suRepo = suRepo;
        this.configuration = configuration;

    }

    @Override
    public Boolean register(ServiceUnitRegisterInfo serviceUnitRegisterInfo) {
        try{
            //直接注册到主库
            MultiTenantContextInfo contextInfo = new MultiTenantContextInfo();
            contextInfo.setMasterDb(true);
            MultiTenantContextHolder.set(contextInfo);
            //执行注册
            this.doRegister();

            msuServiceRegistry.registerServiceUnitInfos(serviceUnitRegisterInfo);
        }finally {
            MultiTenantContextHolder.set(null);
        }
        return true;
    }

    @Override
    @PreDestroy
    public Boolean unRegister() {
        log.info("Db register start unregist su");
        String appName = this.getApplicationName();
        List<String> arr = this.suAware.getEnabledServiceUnits();
        for (var su: arr){
            this.suRepo.deleteByAppAndSu(appName,su.toLowerCase());
        }

        var srv = SpringBeanUtils.getBean(ServiceUnitAwareService.class);
        List<String> suInfoList = srv.getEnabledServiceUnits();
        ServiceUnitRegisterInfo serviceUnitRegisterInfo = srv.getServiceUnitRegisterInfo(configuration.getApplicationName(),configuration.getServiceName(),suInfoList);

        msuServiceRegistry.unRegisterServiceUnitInfos(serviceUnitRegisterInfo);

        log.error("Db register end unregist su");
        return true;

    }

    //todo 没有的su的从这个表里删除
    private void doRegister(){
        String appName = this.getApplicationName();
        List<GspAppServerEntity> entities = this.repo.findByAppName(appName);
        if (entities == null || entities.size() == 0) {
            String ip = this.getLocalIP();
            String port = this.getLocalPort();
            String url = null;
            if(enableSSL()){
                url = String.format("https://%s:%s", ip, port);
            }else{
                url = String.format("http://%s:%s", ip, port);
            }
            GspAppServerEntity entity = new GspAppServerEntity();
            entity.setIp(ip);
            entity.setPort(port);
            entity.setAppName(appName);
            entity.setAppUrl(url);
            //entity.setAppType(ApplicationType.Microservices);
            //entity.setDeployMode(DeployMode.OnPremise);

            this.repo.save(entity);
        }
        //获取su信息，自动注册su
        List<String> arr = this.suAware.getEnabledServiceUnits();
        List<ServiceUnitInfo> infos = this.suAware.getAllServiceUnits();
        /* 开始遍历 */
        if (arr != null) {
            for (String su : arr) {
                ServiceUnitInfo info = infos.stream().filter(s -> s.getName().equals(su)).findFirst().orElse(null);
                if (info != null) {
                    GspSuEntity entity = new GspSuEntity();
                    entity.setApp(appName);
                    entity.setSu(info.getName().toLowerCase());
                    this.suRepo.save(entity);
                }
            }
        }
    }

    /**
     * 返回应用程序名称
     *
     * @return
     */
    private String getApplicationName() {
        Environment env = SpringBeanUtils.getBean(Environment.class);
        String applicationName = env.getProperty("spring.application.name", "");
        if ("".equals(applicationName)) {
            applicationName = env.getProperty("msu.serviceName", "iGIX Server");
        }
        return applicationName;
    }

    /**
     * @return 获取当前机器的IP
     */
    private String getLocalIP() {
        //优先获取外网地址
        String ip = NetUtil.INTERNET_IP;
        //取不到外网地址，则返回内网地址
        if (ip == null || "".equals(ip))
            ip = NetUtil.INTRANET_IP;
        return ip;
    }

    /**
     * @return
     * @throws MalformedObjectNameException 获取当前tomcat机器的端口号
     */
    private String getLocalPort() {
        Environment environment = CafEnvironment.getEnvironment();
        String port = environment.getProperty("local.server.port");
        return port;
    }

    /**
     * @return 是否开启https
     */
    private boolean enableSSL() {
        Environment environment = CafEnvironment.getEnvironment();
        return !StringUtils.isEmpty(environment.getProperty("server.ssl.key-store"));
    }
}
